"""
Copyright (c) Cookie Yang. All right reserved.
"""
from __future__ import print_function
from bcc import BPF
from bcc.utils import printb

# load BPF program
b = BPF(text="""
#include <uapi/linux/ptrace.h>

BPF_HASH(last);  //创建一个BPF映射对象，它是一个散列（关联数组），称为“last”, 默认为 u64 的键和值类型

int do_trace(struct pt_regs *ctx) {
    u64 ts, *tsp, delta, key = 0;  //只会在此哈希中存储一个键/值对，其中键被硬连接为零。

    // attempt to read stored timestamp
    tsp = last.lookup(&key); //在哈希中查找键，如果存在则返回指向其值的指针，否则返回NULL。我们将密钥作为地址传递给指针
    if (tsp != NULL) {  //验证程序要求必须检查从映射查找派生的指针值是否为空值，然后才能取消引用和使用它们
        delta = bpf_ktime_get_ns() - *tsp;
        if (delta < 1000000000) {
            // output if time is less than 1 second
            bpf_trace_printk("%d\\n", delta / 1000000);
        }
        last.delete(&key);  //从哈希中删除密钥。由于4.8.10中的内核错误.update()（已在 4.8.10 中修复），目前需要这样做。
    }

    // update stored timestamp
    ts = bpf_ktime_get_ns();  //返回以纳秒为单位的时间
    last.update(&key, &ts);  //将第二个参数中的值与键关联，覆盖任何先前的值。这记录了时间戳。
    return 0;
}
""")

b.attach_kprobe(event=b.get_syscall_fnname("sync"), fn_name="do_trace")
print("Tracing for quick sync's... Ctrl-C to end")

# format output
start = 0
while 1:
    try:
        (task, pid, cpu, flags, ts, ms) = b.trace_fields()
        if start == 0:
            start = ts
        ts = ts - start
        printb(b"At time %.2f s: multiple syncs detected, last %s ms ago" % (ts, ms))
    except KeyboardInterrupt:
        exit()